import { config } from "dotenv";
import { isString } from "./judge";
import { Argv_Enum } from "../enum/app.enum";
import minimist from "minimist";
import path from "path";

//minimist作用如下
//$ node example/parse.js -a beep -b boop
//{ _: [], a: 'beep', b: 'boop' }

export class EnvHandle {

  private static _instance: Nullable<EnvHandle> = null;

  public static factory() {
    return this._instance ?? (this._instance = new this());
  }

  constructor() {
    this.initEnv();
  }

  private _envConfig: Record<string, string | undefined> = {};

  get envConfig(): typeof this._envConfig {
    return this._envConfig;
  }

  //初始化env
  public initEnv(): void {

    try {
      const getNodeEnv = () => getArgv(Argv_Enum.MODE);

      const getEnvPath = () => {
        if (getNodeEnv() && isString(getNodeEnv()))
          return path.resolve(`env/.${getNodeEnv()}.env`);
        return path.resolve("env/.env");
      };

      const baseEnv = config({ path: getEnvPath() }).parsed!;

      for(let key in baseEnv){
        process.env[key] = this._envConfig[key]
      }

      this._envConfig = Object.assign({},process.env,baseEnv)

    } catch (err) {
      throw new Error("初始化env参数失败：" + err);
    }
  }

  //写入setEnv
  public setEnv(key: string, value: string, cover: boolean = true): boolean {
    try {
      if (this._envConfig[key] && !cover) return false;

      this._envConfig[key] = value;

      try {
        //渲染进程掉不了Process 虽然electron Polyfilled 的全局模块 包括process https://www.electronjs.org/zh/docs/latest/tutorial/tutorial-preload
        //但是vite不允许调process 目前找到trycatch这种兼容方法 后面再说
        process.env[key] = value;
      } catch {}

      return true;
    } catch {
      throw new Error("写入env失败：key" + key + "&value：" + value);
    }
  }

  //获取env
  public getEnv(key:string,validate:boolean = false):string | undefined{

    const val = this._envConfig[key]

    if(!val && validate) throw new Error('未用有env，key：'+ key)

    return val ?? undefined   
  }
  
}

export const Env = new EnvHandle();

/**
 * 获取argv参数
 *
 */
export function getArgv():undefined | minimist.ParsedArgs
export function getArgv(param:Argv_Enum):undefined | string
export function getArgv(param?:Argv_Enum):any {
  
    const argv = minimist(process.argv.slice(2));
    return  param ? argv[param] : argv

}
